from fastapi import HTTPException
from starlette import status
from common.security import get_password_hash, verify_password
from app.users.models import User
from typing import Optional
from datetime import date
from sqlmodel import Session, select


def select_user_by_account(session: Session, account) -> User:
    # from sqlalchemy import or_
    # SQLAlchemy 的 or_()函数: statement = select(User).where(or_(User.email == account, User.phone == account))
    statement = select(User).where((User.email == account) | (User.phone == account))
    session_user = session.exec(statement).first()
    return session_user


def authenticate(*, session: Session, account: str, password: str) -> User | None:
    db_user = select_user_by_account(session=session, account=account)
    if not db_user:
        return None
    if not verify_password(password, db_user.password):
        return None
    return db_user


def create_user(session: Session, name: str, password: str, email: Optional[str] = None, phone: Optional[str] = None,
                birthday: Optional[date] = None, is_active: bool = False) -> User:
    """
    创建新用户并保存到数据库

    参数:
        session: SQLModel 会话
        name: 用户名
        password: 密码(应当在前端或服务层加密后再传入)
        email: 邮箱
        phone: 电话(可选)
        birthday: 生日(可选)
        is_active: 是否激活(默认False)

    返回:
        创建的用户对象
    """
    # 创建用户对象

    if not phone and not email:
        raise ValueError("至少需要提供手机号或邮箱其中之一")
    user = User(
        name=name,
        password=get_password_hash(password),
        email=email,
        phone=phone,
        birthday=birthday,
        is_active=is_active
        # create_time 和 update_time 会自动由数据库设置
    )

    # 添加到会话并提交
    session.add(user)
    session.commit()
    session.refresh(user)  # 刷新以获取数据库生成的字段如id

    return user


def update_user(session: Session, user, **update_data) -> User:


    """
    通用用户更新函数

    :param user: users.models.User 要更新的用户对象
    :param session: SQLModel <数据库会话>
    :param update_data: dict 要更新的字段键值对

    :return user: object对象
    """
    try:
        for key, value in update_data.items():
            setattr(user, key, value)

        session.add(user)
        session.commit()
        session.refresh(user)
        return user
    except Exception as e:
        session.rollback()
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Error updating user: {str(e)}"
        )
